package vip.xiaonuo.sys.modular.wechat.api.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.qq.weixin.mp.aes.AesException;
import com.qq.weixin.mp.aes.WXBizMsgCrypt;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import vip.xiaonuo.common.cache.CommonCacheOperator;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.listener.CommonDataChangeEventCenter;
import vip.xiaonuo.common.util.*;
import vip.xiaonuo.common.wechat.enums.WechatEventEnum;
import vip.xiaonuo.sys.api.dto.WechatLoginCallbackDto;
import vip.xiaonuo.sys.core.enums.SysDataTypeEnum;
import vip.xiaonuo.sys.modular.user.entity.SysUser;
import vip.xiaonuo.sys.modular.user.service.SysUserService;
import vip.xiaonuo.sys.modular.wechat.api.config.WechatProperties;
import vip.xiaonuo.sys.modular.wechat.api.dto.WeChatSensitiveUser;
import vip.xiaonuo.sys.modular.wechat.api.dto.WechatCheckinResponse;
import vip.xiaonuo.sys.modular.wechat.api.dto.WechatEventMessage;
import vip.xiaonuo.sys.modular.wechat.api.dto.WechatNoSensitiveUser;
import vip.xiaonuo.sys.modular.wechat.api.service.WechatService;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author zjt
 * @description
 * @date 2025/7/15 14:21
 */
@Slf4j
@Service
@RequiredArgsConstructor

public class WechatServiceImpl implements WechatService {

    private static final String WECHAT_TOKEN = "wechat_token";
    private final CommonCacheOperator cacheOperator;
    private final SysUserService userService;
    private final ReentrantLock lock = new ReentrantLock();
    private final RedissonClient redissonClient;
    private final SysUserService sysUserService;

    private final WechatProperties wechatProperties;

    private static String httpGetToken() {
        String resp = CommonHttpUtil.post("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=wwe4c18b63c565e438&corpsecret=6K75Pus_VSw5ma8JHOq6jUWYWljR_B1IdqUY-hE4KEk", null, null, null);
        Map<String, Object> respJson = JSONObject.parseObject(resp, HashMap.class);
        if ((int) respJson.get("errcode") == 0) {
            return (String) respJson.get("access_token");
        }
        return null;
    }

    /**
     * 获取Token
     *
     * @return
     */
    @Override
    public String getToken() {
        // 先从缓存获取token
        String token = cacheOperator.getCatchString(WECHAT_TOKEN);
        if (StringUtils.isNotBlank(token)) {
            return token;
        }
        // 获取分布式锁
        RLock rLock = redissonClient.getLock("wechat_lock");
        try {
            // 尝试加锁，等待时间5秒，锁有效期30秒
            boolean locked = rLock.tryLock(5, 15, TimeUnit.SECONDS);
            if (locked) {
                // 双重检查，防止其他线程已经更新了token
                token = cacheOperator.getCatchString(WECHAT_TOKEN);
                if (StringUtils.isBlank(token)) {
                    // 调用企业微信接口获取新token
                    token = httpGetToken();
                    if (StringUtils.isNotBlank(token)) {
                        // 存入缓存，设置过期时间（微信token通常2小时过期）
                        cacheOperator.setCatchString(WECHAT_TOKEN, token, 7000);
                    }
                }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new CommonException("获取微信token时被中断", e);
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return token;
    }

    /**
     * 根据登录Code获取企业微信ID
     *
     * @param loginCode
     * @return
     */
    @Override
    public WechatLoginCallbackDto getWechatCallbackByLoginCode(String loginCode) {
        String resp = CommonHttpUtil.post("https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=" + getToken() + "&code=" + loginCode, null, null, "企业微信--->根据登录Code获取用户信息：" + loginCode);
        return JSONObject.parseObject(resp, WechatLoginCallbackDto.class);
    }

    /**
     * 保存企业微信敏感信息
     *
     * @param userTicket
     * @param userId
     */
    @Override
    public void saveSensitiveData(String userTicket, String userId) {
        String token = getToken();
        WeChatSensitiveUser sensitiveUser = getUserByUserTicket(token, userTicket);
        SysUser sysUser = sysUserService.getById(userId);
        sysUser.setGender(sensitiveUser.getGender() == 1 ? "男" : "女");
        sysUser.setAvatar(sensitiveUser.getAvatar());
        sysUser.setEmail(sensitiveUser.getBiz_mail());
        sysUser.setPhone(sensitiveUser.getMobile());
        if (StringUtils.isBlank(sysUser.getPassword())) {
            String password = PasswordUtil.generatePassword();
            sysUser.setPassword(CommonCryptogramUtil.doHashValue(password));
            String content = "您的自研系统账号已开通\n" +
                    "登录地址：https://www.guozhengxin.com.cn\n" +
                    "账号：" + sysUser.getEmpNo() + "\n" +
                    "密码：" + password + "\n" +
                    "本消息为系统消息，无需回复\n" +
                    "如登录有问题，请联系本部门的郭浩楠";
            sendTextMessage(sysUser.getEmpNo(), content);
        }
        sysUserService.updateById(sysUser);
        // 发布更新事件
        CommonDataChangeEventCenter.doUpdateWithData(SysDataTypeEnum.USER.getValue(), JSONUtil.createArray().put(sysUser));
    }

    /**
     * 发送文本消息
     *
     * @param toUserId 收件人，逗号隔开
     * @param content
     */
    @Override
    public void sendTextMessage(String toUserId, String content) {
        Map<String, Object> msgMap = new HashMap<>();
        msgMap.put("touser", toUserId);
        msgMap.put("msgtype", "text");
        msgMap.put("agentid", wechatProperties.getAgentId());
        Map<String, Object> textContent = new HashMap<>();
        textContent.put("content", content);
        msgMap.put("text", textContent);
        CommonHttpUtil.post("https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + getToken(), null, JSON.toJSONString(msgMap), "企业微信发送应用通知");
    }

    /**
     * 根据微信ID获取用户信息
     *
     * @param userId
     * @return
     */
    @Override
    public WechatNoSensitiveUser getUserById(String userId) {
        String resp = CommonHttpUtil.get("https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=" + getToken() + "&userid=" + userId, null);
        return JSONObject.parseObject(resp, WechatNoSensitiveUser.class);
    }

    /**
     * 企业微信回调
     *
     * @param msgSignature
     * @param timestamp
     * @param nonce
     * @param postData
     */
    @Override
    public void callback(String msgSignature, String timestamp, String nonce, String postData) {
        Thread.startVirtualThread(() -> {
            log.info("收到企业微信的回调：{}，{}，{}，{}", msgSignature, timestamp, nonce, postData);
            WXBizMsgCrypt wxBizMsgCrypt = null;
            String msg = null;
            try {
                wxBizMsgCrypt = new WXBizMsgCrypt(wechatProperties.getToken(), wechatProperties.getAesKey(), wechatProperties.getCorpId());
                msg = wxBizMsgCrypt.decryptMsg(msgSignature, timestamp, nonce, postData);
                wechatEventCallback(CommonXmlUtil.xmlToBean(msg, WechatEventMessage.class));

            } catch (AesException e) {
                throw new CommonException("企业微信的回调，解密失败");
            }
        });
    }

    @Override
    public void wechatEvent(String msg) {
        wechatEventCallback(JSONObject.parseObject(msg, WechatEventMessage.class));
    }

    /**
     * 获取打卡记录
     *
     * @param currentTime
     * @param beforeTime
     * @param userIdList
     * @return
     */
    @Override
    public WechatCheckinResponse getCheckinRecord(String currentTime, String beforeTime, List<String> userIdList) {
        String dakaUrl = "https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckindata?access_token=" + getToken();
        Map<String, Object> aa = new HashMap<>();
        aa.put("opencheckindatatype", 3);
        aa.put("starttime", CommonDateUtil.toUint32Timestamp(beforeTime));
        aa.put("endtime", CommonDateUtil.toUint32Timestamp(currentTime));
        aa.put("useridlist", userIdList);
        String resp = CommonHttpUtil.post(dakaUrl, null, JSON.toJSONString(aa), null);
        return JSONObject.parseObject(resp, WechatCheckinResponse.class);
    }

    private WeChatSensitiveUser getUserByUserTicket(String token, String userTicket) {
        String resp = CommonHttpUtil.post("https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail?access_token=" + token, null, JSON.toJSONString(Map.of("user_ticket", userTicket)), "企业微信--->根据UserTicket获取用户敏感信息信息：" + userTicket);
        return JSONObject.parseObject(resp, WeChatSensitiveUser.class);
    }

    private void wechatEventCallback(WechatEventMessage message) {
        if (message != null) {
            if (cacheOperator.setIfAbsent(message.getChangeType() + "_" + message.getUserID(), System.currentTimeMillis(), 30)) {
                //创建用户
                if (message.getChangeType().equals(WechatEventEnum.CREATE_USER.getType())) {
                    WechatNoSensitiveUser userNoSensitive = getUserById(message.getUserID());
                    userService.addByWechat(userNoSensitive);
                }
                //修改用户
                if (message.getChangeType().equals(WechatEventEnum.UPDATE_USER.getType())) {
//                            userService.disableUser(message.getUserID());
                }
                //删除用户
                if (message.getChangeType().equals(WechatEventEnum.DELETE_USER.getType())) {
                    userService.disableUser(message.getUserID());
                }
            }
        }
    }
}
